package com.learning.concurrent.basic.singleton;

import lombok.extern.slf4j.Slf4j;

/**
 * description:
 *
 * @author minghuiZhang
 * @date created in  17:15 2018/5/10
 * modified by
 */
@Slf4j
public class DoubleCheckSingleton {
	private static DoubleCheckSingleton doubleCheckSingleton;
	public static DoubleCheckSingleton doubleCheckSingleton(){
		log.info("当前线程：进入doubleCheckSingleton方法",Thread.currentThread().getName());
		if (doubleCheckSingleton == null){
			log.info("当前线程：{},if (doubleCheckSingleton == null){",Thread.currentThread().getName());
			try {
				//模拟初始化对象的准备时间
				Thread.sleep(3000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			synchronized (DoubleCheckSingleton.class){
				log.info("当前线程：{},进入同步块",Thread.currentThread().getName());
				//做双重非空检查的原因是因为，当三个线程启动之后，全都进入到第一次if判断里面，之后，其中一个线程首先获得锁，创建对象，如果不加二次非空检查，
				// 因为三个线程已经到达synchronized关键字处，所以其他两个线程仍然会创建对象。也就不能实现线程安全
				if (doubleCheckSingleton == null){
					log.info("当前线程：{},创建对象",Thread.currentThread().getName());
					doubleCheckSingleton = new DoubleCheckSingleton();
				}
			}

		}
		return doubleCheckSingleton;
	}

	public static void main(String[] args) {
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(DoubleCheckSingleton.doubleCheckSingleton().hashCode());
			}
		},"t1");
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(DoubleCheckSingleton.doubleCheckSingleton().hashCode());
			}
		},"t2");
		Thread t3 = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(DoubleCheckSingleton.doubleCheckSingleton().hashCode());
			}
		},"t3");

		t1.start();
		t2.start();
		t3.start();
	}

}
